import subprocess
import threading
import time
import logging
from typing import Optional, Dict, List
from log_config import logger


class RouteManager:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:
                    cls._instance = super(RouteManager, cls).__new__(cls)
        return cls._instance

    def __init__(self, check_interval: int = 10):

        if hasattr(self, "_initialized") and self._initialized:
            return  # 防止重复初始化

        self.check_interval = check_interval
        self.eth0_info = {}  # 保存 eth0 的路由信息
        self.running = False
        self.thread = None

    def _run_ip_command(self, command: str) -> str:
        """执行 ip 命令并返回输出（Python 3.6 兼容版本）"""
        try:
            result = subprocess.run(
                command.split(),
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
            )
            return result.stdout.strip()
        except subprocess.CalledProcessError as e:
            logger.error("Command failed: %s, error: %s", command, e.stderr)
            return ""

    def _get_default_routes(self) -> List[str]:
        """获取所有默认路由（严格匹配default开头的路由）"""
        output = self._run_ip_command("ip route show default")
        return [line for line in output.split("\n") if line.startswith("default")]

    def _get_eth0_info(self) -> Optional[Dict]:
        """获取 eth0 的 IP 和网关信息"""
        # 获取 IP 地址
        ip_output = self._run_ip_command("ip addr show eth0")
        ip_match = [line.strip() for line in ip_output.split("\n") if "inet " in line]
        if not ip_match:
            return None

        ip_info = ip_match[0].split()
        ip_address = ip_info[1].split("/")[0]

        # 获取网关（如果有）
        route_output = self._run_ip_command("ip route show dev eth0")
        gateway_match = [
            line for line in route_output.split("\n") if "default via " in line
        ]
        gateway = gateway_match[0].split()[2] if gateway_match else None

        return {"interface": "eth0", "ip": ip_address, "gateway": gateway}

    def _save_eth0_info(self):
        """保存 eth0 的路由信息"""
        info = self._get_eth0_info()
        if info:
            self.eth0_info = info
            logger.info(f"Saved eth0 info: {info}")
        else:
            logger.warning("Could not get eth0 info to save")

    def _delete_eth0_route(self):
        """删除 eth0 的默认路由"""
        if not self.eth0_info.get("gateway"):
            logger.warning("No saved gateway for eth0 to delete")
            return

        cmd = f"ip route del default via {self.eth0_info['gateway']} dev eth0"
        self._run_ip_command(cmd)
        logger.info(f"Deleted eth0 default route: {self.eth0_info['gateway']}")

    def _restore_eth0_route(self):
        """恢复 eth0 的默认路由"""
        if not self.eth0_info.get("gateway"):
            logger.warning("No saved gateway for eth0 to restore")
            return

        cmd = f"ip route add default via {self.eth0_info['gateway']} dev eth0"
        self._run_ip_command(cmd)
        logger.info(f"Restored eth0 default route: {self.eth0_info['gateway']}")

    def _check_routes(self):
        """检查并管理路由"""
        default_routes = self._get_default_routes()
        num_routes = len(default_routes)

        logger.info(f"Found {num_routes} default routes: {default_routes}")

        if num_routes == 0:
            # 没有默认路由，尝试恢复 eth0
            if self.eth0_info:
                self._restore_eth0_route()
            else:
                logger.warning("No default routes and no saved eth0 info")
        elif num_routes >= 2:
            # 多个默认路由，删除 eth0 的并保存信息
            eth0_routes = [route for route in default_routes if "dev eth0" in route]
            if eth0_routes:
                self._save_eth0_info()
                self._delete_eth0_route()

    def _worker(self):
        """工作线程的主循环"""
        while self.running:
            self._check_routes()
            time.sleep(self.check_interval)

    def start(self):
        """启动路由管理线程"""
        if self.running:
            logger.warning("Route manager is already running")
            return

        self.running = True
        self.thread = threading.Thread(target=self._worker, daemon=True)
        self.thread.start()
        logger.info("Route manager started")

    def stop(self):
        """停止路由管理线程"""
        if not self.running:
            logger.warning("Route manager is not running")
            return

        self.running = False
        if self.thread:
            self.thread.join()
        logger.info("Route manager stopped")
